home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / l2.arc / MAKOVL.C86 < prev   
Text File  |  1986-02-17  |  19KB  |  786 lines

  1. /* HEADER: CUG120.10;
  2.    TITLE: L2;
  3.    DATE: 00/00/1980;
  4.    DESCRIPTION: "Variation of L2 that creats relocatable overlays
  5.     according to an overlay descriptor file.";
  6.    KEYWORDS: overlay,relocatable,linker;
  7.    SYSTEM: CP/M;
  8.    FILENAME: MAKOVL.C;
  9.    CRC: 3A28;
  10.    SEE-ALSO: CLINK;
  11.    AUTHORS: Scott W. Layson;
  12.    COMPILERS: BDS C;
  13. */
  14. /* MAKOVL.C    Overlay builder/manager
  15.  
  16.     This code is in the public domain.
  17.     Created from L2.C 81.10.29 Gyro
  18.  
  19. This is a variation on L2.C that creates relocatable overlays
  20. according to an overlay descriptor file.
  21.  
  22. Command format:
  23.  
  24.     makovl <root name> <overlay name> {<CRL file>} [-l {<CRL file>}] [-nd]
  25.  
  26. Overlay descriptor file, <root name>.DES, contains:
  27.  
  28.     <overlay slot size> <relocation info size>
  29.     <CRL file> ... (default search list)
  30.     ... (more default search list)
  31.     <blank line>
  32.     <overlay name> <slot number>
  33.         <function name>  <comments or whatnot>
  34.         <function name>  <comments or whatnot>
  35.         ... (an entry for each top-level function in the overlay)
  36.     <blank line>
  37.     <overlay name> <slot number>
  38.         <function name>  <comments or whatnot>
  39.         <function name>  <comments or whatnot>
  40.         ...
  41.     ... (an entry for each overlay in the file)
  42.  
  43.  
  44. Overlay segments are of length <overlay slot size> bytes, of which the
  45. last <relocation info size> bytes holds a list of relocation offsets. 
  46. This is a null-terminated string of byte values giving the difference
  47. between successive addresses to be relocated; a value of 255 means to
  48. add 255 to the next byte value to get the offset.  The first offset is
  49. relative to -1 (so that we can relocate the first word of the
  50. overlay).  At the beginning of the overlay is a table of addresses of
  51. top-level functions, one address for each function listed for that
  52. overlay in the descriptor file.
  53.  
  54. The -l option works as for L2: CRL files listed before the -l are
  55. loaded in entirety; those after are just scanned for needed functions. 
  56. Any functions specified in the default search list in the overlay
  57. descriptor file are also scanned, unless the -nd (no default) option
  58. is given.
  59.  
  60. The overlay, once created, is written into <root name>.OVL, at address
  61. <slot number> * <overlay slot size>.
  62.  
  63. */
  64.  
  65.  
  66. /**************** Globals ****************/
  67.  
  68. #define SDOS                /* comment this out for CP/M */
  69.  
  70. #include "bdscio.h"            /* for i/o buffer defs */
  71.  
  72. #define NUL        0
  73. #define FLAG        char
  74. #define repeat     while (1)
  75.  
  76. #define STDOUT        1
  77.  
  78.  
  79. /* function table */
  80. struct funct {
  81.     char fname[9];
  82.     FLAG flinkedp;            /* in memory already? */
  83.     char *faddr;            /* address of first ref link if not linked */
  84.     } ftab [300];
  85. int nfuncts;                /* no. of functions in table */
  86.  
  87. #define LINKED        255        /* (flinkedp) function really here */
  88. #define EXTERNAL    254        /* function defined in separate symbol table */
  89.  
  90. char fdir [512];            /* CRL file function directory */
  91.  
  92. /* command line parameters etc. */
  93. char rootname[15];            /* name of root program */
  94. char ovlname[40];            /* name of overlay to be built */
  95. int nprogs, nlibs;
  96. char progfiles [20] [15];    /* program file names */
  97. char libfiles [30] [15];        /* library file names */
  98. FLAG srchdefs;                /* search default libraries? */
  99.  
  100. /* overlay description */
  101. int ovlsize, relsize;        /* size of overlay slot & of relocation info */
  102. int ovlslot;                /* slot # to put overlay in */
  103. char topfuncts[10][32];        /* names of top level functions */
  104. int ntops;                /* number of top level functions */
  105. char *relstart;            /* beginning of relocation info */
  106. char *relnext;                /* next relocation value */
  107. char *reladdr;                /* last address relocated */
  108.  
  109.  
  110. /* useful things to have defined */
  111. struct inst {
  112.     char opcode;
  113.     char *address;
  114.     };
  115.  
  116. union ptr {
  117.     unsigned u;            /* an int */
  118.     unsigned *w;            /* a word ptr */
  119.     char *b;                /* a byte ptr */
  120.     struct inst *i;        /* an instruction ptr */
  121.     };
  122.  
  123.  
  124. /* Link control variables */
  125.  
  126. union ptr codend;            /* last used byte of code buffer + 1 */
  127. union ptr acodend;            /* actual code-end address */
  128. unsigned origin;            /* origin of code */
  129. unsigned buforg;            /* origin of code buffer */
  130.  
  131. char *lspace;                /* space to link in */
  132. char *lspcend;                /* end of link area */
  133. char *lodstart;            /* beginning of current file */
  134.  
  135.  
  136. /* i/o buffer */
  137. struct iobuf {
  138.     int fd;
  139.     int isect;            /* currently buffered sector */
  140.     int nextc;            /* index of next char in buffer */
  141.     char buff [128];
  142.     } ibuf, obuf;
  143.  
  144. /* BDS C i/o buffer */
  145. char bdsbuf[BUFSIZ];
  146.  
  147. /* seek opcodes */
  148. #define ABSOLUTE 0
  149. #define RELATIVE 1
  150.  
  151. #define INPUT 0
  152. #define UPDATE 2
  153.  
  154. #define TRUE (-1)
  155. #define FALSE 0
  156. #define NULL 0
  157.  
  158. /* 8080 instructions */
  159. #define LHLD 0x2A
  160. #define LXIH 0x21
  161. #define SPHL 0xF9
  162. #define JMP  0xC3
  163. #define CALL 0xCD
  164.  
  165. /* strcmp7 locals, made global for speed */
  166. char _c1, _c2, _end1, _end2;
  167.  
  168. /**************** End of Globals ****************/
  169.  
  170.  
  171.  
  172. main (argc, argv)
  173.     int argc;
  174.     char **argv;
  175. {
  176.     puts ("Mark of the Unicorn Overlay Builder, vsn. 1.0\n");
  177.     setup (argc, argv);
  178.     linkprog();
  179.     linklibs();
  180.     listfuns();
  181.     wrtovl();
  182.     }
  183.  
  184.  
  185. setup (argc, argv)            /* initialize function table, etc. */
  186.     int argc;
  187.     char **argv;
  188. {
  189.     nprogs = 0;
  190.     nlibs = 0;
  191.     origin = buforg = 0;
  192.     nfuncts = 0;
  193.     srchdefs = TRUE;
  194.     cmdline (argc, argv);
  195.     lspace = endext();
  196.     lspcend = topofmem() - 1024;
  197.     getdesc();
  198.     loadsyms();
  199.     }
  200.  
  201.  
  202. cmdline (argc, argv)        /* process command line */
  203.     int argc;
  204.     char **argv;
  205. {
  206.     int i, progp;
  207.  
  208.     if (argc <= 2) {
  209.         puts ("Usage is:\n");
  210.         puts ("  makovl <root name> <overlay name> {<CRL file>} [-l {<CRL file>}]");
  211.         exit (1);
  212.         }
  213.     strcpy (&rootname, argv[1]);
  214.     strcpy (&ovlname, argv[2]);
  215.     progp = TRUE;
  216.     for (i = 3; i < argc; ++i) {
  217.         if (argv[i][0] == '-') {
  218.             if (!strcmp (argv[i], "-L")) progp = FALSE;
  219.             else if (match (argv[i], "-ND")) srchdefs = FALSE;
  220.             else printf ("Unknown option: '%s'\n", argv[i]);
  221.             }
  222.         else {
  223.             if (progp) strcpy (&progfiles[nprogs++], argv[i]);
  224.             else strcpy (&libfiles[nlibs++], argv[i]);
  225.             }
  226.         }
  227.     }
  228.  
  229.  
  230. getdesc()                    /* get & process overlay description */
  231. {
  232.     makeext (&rootname, "DES");
  233.     if (fopen (&rootname, &bdsbuf) < 0)
  234.         Fatal ("Can't open overlay descriptor file '%s'.\n", &rootname);
  235.     if (fscanf (&bdsbuf, "%d%d", &ovlsize, &relsize) < 2
  236.         ||  ovlsize <= relsize) {
  237.         Fatal ("Error in descriptor file: bad overlay/relocation sizes.\n");
  238.         }
  239.     getlibs();
  240.     findovl();
  241.     readfuns();
  242.     fclose (&bdsbuf);
  243.     }
  244.  
  245.  
  246. getlibs()                    /* get default search list */
  247. {
  248.     char line[MAXLINE], *cp, *dest;
  249.     
  250.     repeat {
  251.         if (!fgets (&line, &bdsbuf)  ||  !line[0]) break;
  252.         if (!srchdefs) continue;
  253.         cp = &line;
  254.         repeat {
  255.             while (isspace (*cp)) ++cp;
  256.             if (!*cp) break;
  257.             dest = &libfiles[nlibs++];
  258.             while (*cp  &&  !isspace (*cp)) *dest++ = *cp++;
  259.             *dest = NUL;
  260.             }
  261.         }
  262.     }
  263.  
  264.  
  265. findovl()                    /* find description of overlay */
  266. {
  267.     char tname[40];
  268.     int nread;
  269.     FLAG skipping, found;
  270.     
  271.     skipping = found = FALSE;
  272.     while (!found
  273.           &&  (nread = fscanf (&bdsbuf, "%s%d", &tname, &ovlslot)) >= 0) {
  274.         if (nread) {
  275.             if (!skipping) {
  276.                 if (match (&tname, &ovlname)) found = TRUE;
  277.                 else skipping = TRUE;
  278.                 }
  279.             }
  280.         else skipping = FALSE;
  281.         }
  282.     if (!found)
  283.         Fatal ("Can't find description of overlay '%s'.\n", &ovlname);
  284.     if (nread < 2) 
  285.         Fatal ("No slot number present for overlay '%s'.\n", &tname);
  286.     printf ("Building overlay %s, for slot %d.\n", &tname, ovlslot);
  287.     }
  288.  
  289.  
  290. readfuns()
  291. {
  292.     char tname[40];
  293.     struct funct *fnct;
  294.     
  295.     ntops = 0;
  296.     RelInit();
  297.     codend.b = lspace;                /* build table of functions */
  298.     puts ("Functions included:\n");
  299.     while (fscanf (&bdsbuf, "%s", &tname) > 0) {
  300.         printf ("%-10s", &tname);
  301.         upcase (&tname);
  302.         tname[8] = NUL;            /* limit size */
  303.         fnct = intern (&tname);
  304.         *codend.w = fnct->faddr;        /* link in reference */
  305.         RelAccum (codend.w);        /* relocate this address */
  306.         fnct->faddr = codend.w++;
  307.         ntops++;
  308.         }
  309.     puts ("\n\n");
  310.     }
  311.  
  312.  
  313. linkprog()                /* link in all program files */
  314. {
  315.     int i;
  316.     union ptr dirtmp;
  317.     struct funct *fnct;
  318.  
  319.     for (i=0; i<nprogs; ++i) {
  320.         makeext (&progfiles[i], "CRL");
  321.         if (copen (&ibuf, progfiles[i]) < 0) {
  322.             printf ("Can't open %s\n", progfiles[i]);
  323.             continue;
  324.             }
  325.         printf ("Loading %s\n", &progfiles[i]);
  326.         readprog (i==0);
  327.         for (dirtmp.b=&fdir; *dirtmp.b != 0x80;) {
  328.             fnct = intern (dirtmp.b);            /* for each module */
  329.             skip7 (&dirtmp);                    /* in directory */
  330.             if (!fnct->flinkedp)
  331.                 linkmod (fnct, lodstart + *dirtmp.w - 0x205);
  332.             else {
  333.                 puts ("  Duplicate program function '");
  334.                 puts (&fnct->fname);
  335.                 puts ("', not linked.\n");
  336.                 }
  337.             dirtmp.w++;
  338.             }                                /* intern & link it */
  339.         cclose (&ibuf);
  340.         }
  341.     }
  342.  
  343.  
  344. linklibs()                /* link in library files */
  345. {
  346.     int ifile;
  347.  
  348.     for (ifile = 0; ifile < nlibs; ++ifile) scanlib (ifile);
  349.     while (missingp()) {
  350.         puts ("Enter the name of a file to be searched: ");
  351.         gets (&libfiles[nlibs]);
  352.         upcase (&libfiles[nlibs]);
  353.         scanlib (nlibs++);
  354.         }
  355.     acodend.b = codend.b - lspace + buforg;        /* save that number! */
  356.     }
  357.  
  358.  
  359. missingp()                /* are any functions missing?  print them out */
  360. {
  361.     int i, foundp;
  362.  
  363.     foundp = FALSE;
  364.     for (i=0; i<nfuncts; ++i)
  365.         if (!ftab[i].flinkedp) {
  366.             if (!foundp) puts ("*** Missing functions:\n");
  367.             puts (&ftab[i].fname);
  368.             puts ("\n");
  369.             foundp = TRUE;
  370.             }
  371.     return (foundp);
  372.     }
  373.  
  374.  
  375. readprog (mainp)            /* read in a program file */
  376.     FLAG mainp;
  377. {
  378.     char extp;                            /* was -e used? */
  379.     char *extstmp;
  380.     union ptr dir;
  381.     unsigned len;
  382.  
  383.     if (cread (&ibuf, &fdir, 512) < 512)            /* read directory */
  384.         Fatal ("-- read error!\n");
  385.     cseek (&ibuf, 5, RELATIVE);
  386.     for (dir.b=&fdir; *dir.b != 0x80; nextd (&dir));    /* find end of dir */
  387.     ++dir.b;
  388.     len = *dir.w - 0x205;
  389.     readobj (len);
  390.     }
  391.  
  392.  
  393. readobj (len)                /* read in an object (program or lib funct) */
  394.     unsigned len;
  395. {
  396.     if (codend.b + len >= lspcend) Fatal ("-- out of memory!\n");
  397.     lodstart = codend.b;
  398.     if (cread (&ibuf, lodstart, len) < len)
  399.         Fatal ("-- read error (read 0x%x)!\n", len);
  400.     }
  401.  
  402.  
  403. scanlib (ifile)
  404.     int ifile;
  405. {
  406.     int i;
  407.     union ptr dirtmp;
  408.  
  409.     makeext (&libfiles[ifile], "CRL");
  410.     if (copen (&ibuf, libfiles[ifile]) < 0) {
  411.         printf ("Can't open %s\n", libfiles[ifile]);
  412.         return;
  413.         }
  414.     printf ("Scanning %s\n", &libfiles[ifile]);
  415.     if (cread (&ibuf, &fdir, 512) < 512)    /* read directory */
  416.         Fatal ("-- Read error (directory)!\n");
  417.     for (i=0; i<nfuncts; ++i) {            /* scan needed functions */
  418.         if (!ftab[i].flinkedp
  419.             && (dirtmp.b = dirsearch (&ftab[i].fname))) {
  420.             readfunct (dirtmp.b);
  421.             linkmod (&ftab[i], lodstart);
  422.             }
  423.         }
  424.     cclose (&ibuf);
  425.     }
  426.  
  427.  
  428. readfunct (direntry)            /* read a function (from a library) */
  429.     union ptr direntry;
  430. {
  431.     unsigned start, len;
  432.  
  433.     skip7 (&direntry);
  434.     start = *direntry.w++;
  435.     skip7 (&direntry);
  436.     len = *direntry.w - start;
  437.     if (cseek (&ibuf, start, ABSOLUTE) < 0)
  438.         Fatal (" -- read error (seek 0x%x)!", start);
  439.     readobj (len);
  440.     }
  441.  
  442.  
  443. linkmod (fnct, modstart)            /* link in a module */
  444.     struct funct *fnct;
  445.     union ptr    modstart;                    /* loc. of module in memory */
  446.  
  447. {
  448.     union ptr temp,
  449.             jump,                    /* jump table temp */
  450.             body,                    /* loc. of function in memory */
  451.             code,                    /* loc. of code proper in mem. */
  452.             finalloc;                    /* runtime loc. of function */
  453.     unsigned flen, nrelocs, jtsiz, offset;
  454.  
  455.     fnct->flinkedp = LINKED;
  456.     finalloc.b = codend.b - lspace + buforg;
  457.     chase (fnct->faddr, finalloc.b);
  458.     fnct->faddr = finalloc.b;
  459.     body.b = modstart.b + strlen(modstart.b) + 3; /* loc. of function body */
  460.     jump.i = body.i + (*modstart.b ? 1 : 0);
  461.     for (temp.b = modstart.b; *temp.b; skip7(&temp)) {
  462.         jump.i->address = intern (temp.b);
  463.         ++jump.i;
  464.         }
  465.     ++temp.b;
  466.     flen = *temp.w;
  467.     code.b = jump.b;
  468.     temp.b = body.b + flen;                /* loc. of reloc parameters */
  469.     nrelocs = *temp.w++;
  470.     jtsiz = code.b - body.b;
  471.     offset = code.b - codend.b;
  472.     while (nrelocs--) relocate (*temp.w++, body.b, jtsiz,
  473.                            finalloc.b, offset, flen);
  474.     flen -= jtsiz;
  475.     movmem (code.b, codend.b, flen);
  476.     codend.b += flen;
  477.     }
  478.  
  479.  
  480. relocate (param, body, jtsiz, base, offset, flen)    /* do a relocation!! */
  481.     unsigned param, jtsiz, base, offset, flen;
  482.     union ptr body;
  483. {
  484.     union ptr instr,                    /* instruction involved */
  485.             ref;                        /* jump table link */
  486.     struct funct *fnct;
  487.  
  488.     if (param == 1  &&  jtsiz) return;        /* don't reloc jt skip */
  489.     instr.b = body.b + param - 1;
  490.     if (instr.i->address >= jtsiz) {
  491.         instr.i->address += base - jtsiz;
  492.         RelAccum (body.b + param - offset);
  493.         }
  494.     else {
  495.         ref.b = instr.i->address + body.u;
  496.         if (instr.i->opcode == LHLD) {
  497.             instr.i->opcode = LXIH;
  498.             --ref.b;
  499.             }
  500.         fnct = ref.i->address;
  501.         instr.i->address = fnct->faddr;        /* link in */
  502.         if (!fnct->flinkedp)
  503.             fnct->faddr = instr.b + 1 - offset;    /* new list head */
  504.         if (fnct->flinkedp != EXTERNAL) RelAccum (instr.b + 1 - offset);
  505.         }
  506.     }
  507.  
  508.  
  509. intern (name)                /* intern a function name in the table */
  510.     char *name;
  511. {
  512.     struct funct *fptr;
  513.  
  514.     if (*name == 0x9D) name = "MAIN";        /* Why, Leor, WHY??? */
  515.     for (fptr = &ftab[nfuncts-1]; fptr >= ftab; --fptr) 
  516.         if (!strcmp7 (name, fptr->fname)) break;
  517.     if (fptr < ftab) {
  518.         fptr = &ftab[nfuncts];
  519.         strcpy7 (fptr->fname, name);
  520.         str7tont (fptr->fname);
  521.         fptr->flinkedp = FALSE;
  522.         fptr->faddr = NULL;
  523.         ++nfuncts;
  524.         }
  525.     return (fptr);
  526.     }
  527.  
  528.  
  529. dirsearch (name)            /* search directory for a function */
  530.     char *name;
  531. {
  532.     union ptr temp;
  533.  
  534.     for (temp.b = &fdir; *temp.b != 0x80; nextd (&temp))
  535.         if (!strcmp7 (name, temp.b)) return (temp.b);
  536.     return (NULL);
  537.     }
  538.  
  539.  
  540. nextd (ptrp)                /* move this pointer to the next dir entry */
  541.     union ptr *ptrp;
  542. {
  543.     skip7 (ptrp);
  544.     ++(*ptrp).w;
  545.     }
  546.  
  547.  
  548. chase (head, loc)            /* chase chain of refs to function */
  549.     union ptr head;
  550.     unsigned loc;
  551. {
  552.     union ptr temp;
  553.  
  554.     while (head.w) {
  555.         temp.w = *head.w;
  556.         *head.w = loc;
  557.         head.u = temp.u;
  558.         }
  559.     }
  560.  
  561.  
  562. RelInit()                    /* initialize relocation accumulator */
  563. {
  564.     relstart = relnext = lspace;
  565.     lspace += relsize;                /* allocate some memory for relocs */
  566.     reladdr = lspace - 1;
  567.     }
  568.  
  569.  
  570. RelAccum (addr)            /* note another relocation */
  571.     char *addr;
  572. {
  573.     unsigned delta;
  574.     
  575.     if (relnext - relstart >= relsize) {
  576.         Deadly ("Out of relocation bytes (limit is %d)\n", relsize);
  577.         relnext = relstart;
  578.         }
  579.     delta = addr - reladdr;
  580.     if (delta >= 255) {
  581.         *relnext++ = 255;
  582.         *relnext++ = delta - 255;
  583.         }
  584.     else *relnext++ = delta;
  585.     reladdr = addr;
  586.     }
  587.  
  588.  
  589. RelFini()                    /* end of relocations */
  590. {
  591.     printf ("Relocation bytes used: %d (limit is %d)\n",
  592.                relnext - relstart, relsize);
  593.     *relnext = NUL;
  594.     }
  595.  
  596.  
  597. wrtovl()                    /* write overlay into slot */
  598. {
  599.     int ovlfd;
  600.     
  601.     RelFini();
  602.     if (codend.b > lspace + ovlsize - relsize)
  603.         Deadly ("Code too long!\n");
  604.     movmem (relstart, lspace + ovlsize - relsize, relsize);
  605.     makeext (&rootname, "OVL");
  606.     if ((ovlfd = open (&rootname, UPDATE)) < 0)
  607.         Fatal ("Can't open overlay file '%s'.\n", rootname);
  608.     if (seek (ovlfd, ovlslot * ovlsize / 128, ABSOLUTE) == -1
  609.         ||  write (ovlfd, lspace, ovlsize / 128) == -1)
  610.         Fatal ("Disk write error.  Check slot # and size of .OVL file.\n");
  611.     close (ovlfd);
  612.     }
  613.  
  614.  
  615. listfuns()                /* list functions linked */
  616. {
  617.     int i, compar();
  618.     
  619.     for (i = 0; i < ntops; ++i) ftab[i].flinkedp = i;
  620.     while (i < nfuncts  &&  ftab[i].flinkedp == EXTERNAL) i++;
  621.     arydel (&ftab, nfuncts, sizeof(*ftab), ntops, i);
  622.     nfuncts -= i - ntops;
  623.     qsort (&ftab, nfuncts, sizeof(*ftab), &compar);
  624.     ftab[nfuncts].faddr = acodend.b;
  625.     puts ("\nContents of overlay:\n");
  626.     puts ("Entry no.   Name        Start     Length\n");
  627.     for (i = 0; i < nfuncts; ++i) {
  628.         if (ftab[i].flinkedp < 255) printf ("%8d", ftab[i].flinkedp);
  629.         else puts ("        ");
  630.         printf ("    %-8s    0x%4x    0x%4x\n",
  631.                ftab[i].fname, ftab[i].faddr,
  632.                ftab[i+1].faddr - ftab[i].faddr);
  633.         }
  634.     printf ("End address: 0x%x\n", acodend.u);
  635.     i = ovlsize - relsize - acodend.u;
  636.     printf ("Code bytes remaining: 0x%x = %d.\n\n", i, i);
  637.     }
  638.  
  639.  
  640. compar (f1, f2)            /* compare two symbol table entries by name */
  641.     struct funct *f1, *f2;
  642. {
  643. /*    return (strcmp (&f1->fname, &f2->fname));    alphabetical order */
  644.     return (f1->faddr > f2->faddr);            /* memory order */
  645.     }
  646.  
  647.  
  648. loadsyms()                /* load base symbol table (for overlay) */
  649. {                        /* symbol table must be empty! */
  650.     int nread;
  651.     FLAG done;
  652.     char *c;
  653.     
  654.     makeext (&rootname, "SYM");
  655.     if (fopen (&rootname, &bdsbuf) < 0) 
  656.         Fatal ("Can't open %s.\n", &rootname);
  657.     done = FALSE;
  658.     while (!done) {
  659.         nread = fscanf (&bdsbuf, "%x%s%x%s%x%s%x%s",
  660.                      &(ftab[nfuncts].faddr), &(ftab[nfuncts].fname),
  661.                      &(ftab[nfuncts+1].faddr), &(ftab[nfuncts+1].fname),
  662.                      &(ftab[nfuncts+2].faddr), &(ftab[nfuncts+2].fname),
  663.                      &(ftab[nfuncts+3].faddr), &(ftab[nfuncts+3].fname));
  664.         nread /= 2;
  665.         if (nread < 4) done = TRUE;
  666.         while (nread-- > 0) ftab[nfuncts++].flinkedp = EXTERNAL;
  667.         }
  668.     fclose (&bdsbuf);
  669.     }
  670.  
  671.  
  672. makeext (fname, ext)        /* force a file extension to ext */
  673.     char *fname, *ext;
  674. {
  675.     while (*fname && (*fname != '.')) {
  676.         *fname = toupper (*fname);        /* upcase as well */
  677.         ++fname;
  678.         }
  679.     *fname++ = '.';
  680.     strcpy (fname, ext);
  681.     }
  682.  
  683.  
  684. strcmp7 (s1, s2)            /* compare two bit-7-terminated strings */
  685.     char *s1, *s2;            /* also works for non-null NUL-term strings */
  686. {
  687. /*    char c1, c2, end1, end2;        (These are now global for speed) */
  688.  
  689.     repeat {
  690.          _c1 = *s1++;
  691.         _c2 = *s2++;
  692.         _end1 = (_c1 & 0x80) | !*s1;
  693.         _end2 = (_c2 & 0x80) | !*s2;
  694.         if ((_c1 &= 0x7F) < (_c2 &= 0x7F)) return (-1);
  695.         if (_c1 > _c2  ||  (_end2  &&  !_end1)) return (1);
  696.         if (_end1  &&  !_end2) return (-1);
  697.         if (_end1  &&  _end2) return (0);
  698.         }
  699.     }
  700.  
  701.  
  702. strcpy7 (s1, s2)            /* copy s2 into s1 */
  703.     char *s1, *s2;
  704. {
  705.     do {
  706.         *s1 = *s2;
  707.         if (!*(s2+1)) {                /* works even if */
  708.             *s1 |= 0x80;                /* s2 is null-term */
  709.             break;
  710.             }
  711.         ++s1;
  712.         } while (!(*s2++ & 0x80));
  713.     }
  714.  
  715.  
  716. skip7 (ptr7)                /* move this pointer past a string */
  717.     char **ptr7;
  718. {
  719.     while (!(*(*ptr7)++ & 0x80));
  720.     }
  721.  
  722.  
  723. str7tont (s)                /* add null at end */
  724.     char *s;
  725. {
  726.     while (!(*s & 0x80)) {
  727.         if (!*s) return;        /* already nul term! */
  728.         s++;
  729.         }
  730.     *s = *s & 0x7F;
  731.     *++s = NUL;
  732.     }
  733.  
  734.  
  735. puthex (n, obuf)            /* output a hex word, with leading 0s */
  736.     unsigned n;
  737.     char *obuf;
  738. {
  739.     int i, nyb;
  740.     
  741.     for (i = 3; i >= 0; --i) {
  742.         nyb = (n >> (i * 4)) & 0xF;
  743.         nyb += (nyb > 9) ? 'A' - 10 : '0';
  744.         putc (nyb, obuf);
  745.         }
  746.     }
  747.  
  748.  
  749. Fatal (arg1, arg2, arg3, arg4)    /* lose, lose */
  750.     char *arg1, *arg2, *arg3, *arg4;
  751. {
  752.     printf (arg1, arg2, arg3, arg4);
  753.     exit (1);
  754.     }
  755.  
  756.  
  757. Deadly (arg1, arg2, arg3, arg4)    /* partially-recoverable error */
  758.     char *arg1, *arg2, *arg3, *arg4;
  759. {
  760.     printf (arg1, arg2, arg3, arg4);
  761.     puts ("   -- overlay being generated anyway, for debugging.\n");
  762.     }
  763.  
  764.  
  765. exit (status)                /* exit the program */
  766.     int status;
  767. {
  768.     if (status == 1) {
  769. #ifdef SDOS
  770.         unlink ("a:$$$$.cmd");
  771. #else
  772.         unlink ("a:$$$.sub");
  773. #endif
  774.         }
  775.     bios (1);                    /* bye! */
  776.     }
  777.  
  778.  
  779. /* End of MAKOVL.C  --  link and store relocatable overlay */
  780. ext;
  781. {
  782.     while (*fname && (*fname != '.')) {
  783.         *fname = toupper (*fname);        /* upcase as well */
  784.         ++fname;
  785.         }
  786.     *fname++ =